package com.best.oasis.settlement.service.security;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.best.oasis.settlement.common.entity.security.Role;
import com.best.oasis.settlement.common.entity.security.RoleGroup;
import com.best.oasis.settlement.common.so.security.RoleSO;
import com.best.oasis.settlement.common.vo.security.CheckedRoleTreeVO;
import com.best.oasis.settlement.common.vo.security.RoleGroupVO;
import com.best.oasis.settlement.common.vo.security.RoleVO;
import com.best.oasis.settlement.common.vo.security.UserVO;
import com.best.oasis.settlement.dao.security.RoleDao;
import com.best.oasis.settlement.dao.security.RoleGroupDao;
import com.best.oasis.settlement.service.base.BaseServiceImpl;
import com.best.oasis.settlement.util.SecurityUtil;
import com.best.oasis.settlement.util.convert.ConvertUtil;
import com.best.oasis.settlement.util.page.BasePageSO;
import com.best.oasis.settlement.util.page.OrderType;
import com.best.oasis.util.tree.FlatTreeNode;
import com.best.oasis.util.tree.TreeNode;
import com.best.oasis.util.tree.TreeUtil;
import com.best.oasis.util.tree.Visitor;

@Service
public class RoleServiceImpl extends BaseServiceImpl<Role, RoleVO, Long>
		implements RoleService {
	@Autowired
	private RoleDao roleDao;
	
	@Autowired
	private RoleGroupDao roleGroupDao;
	@Autowired
	private UserService userService;
	public RoleServiceImpl() {
		super.setBaseDao(roleDao);
	}

	@Autowired
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}

	@Override
	public void afterConstruct() {
		super.setBaseDao(roleDao);
		super.setEntityClass(Role.class);
		super.setEntityVOClass(RoleVO.class);
	}

	// public List<RoleVO> getRootRoleList() {
	// List<RoleVO> result = new ArrayList<RoleVO>();
	// result =
	// (List<RoleVO>)dozerBeanUtil.convertList(roleDao.getRootRoleList(),
	// entityVOClass);
	// return result;
	// }
	@Override
	public TreeNode getTree(Long groupId) {
		TreeNode result = null;

		result = buildTree(groupId);
		
		return result;
	}

	@Override
	public CheckedRoleTreeVO getCheckedRoleTree(Long groupId) {
		CheckedRoleTreeVO checkedRoleTreeVo=new CheckedRoleTreeVO();
		List<RoleVO> checkedRoles= new ArrayList<RoleVO>();
		TreeNode roleTree = null;
		//从数据库中把全部的Role数据取出，然后创建一颗树
		roleTree = buildTree(groupId);
		
		List<String> checkedRoleKeyList = redefineCheckedNodeKeys(roleTree ,groupId);
		List<Long> checkedRoleIdList=ConvertUtil.toLongs(checkedRoleKeyList);
		if(checkedRoleIdList!=null && checkedRoleIdList.size()>0){
			List<Long> tmpList = new ArrayList<Long>();
			int currentCount = 0;
			int size =  checkedRoleIdList.size();
			int length = 0;
			while( currentCount < size ){
				if( size - currentCount > 800 ){
					length = currentCount + 800;
				}else{
					length = checkedRoleIdList.size();
				}
				for( int index = currentCount; index < length ; index++ ){
					tmpList.add(checkedRoleIdList.get(index));
				}
				checkedRoles.addAll(getByIds(tmpList));
				if( tmpList != null ){
					tmpList.clear();
				}
				currentCount = length;
			}		
		}		
		//重新标记整棵树中存在的权限
		TreeUtil.markCheckedNode(roleTree, checkedRoleKeyList);
		
		checkedRoleTreeVo.setCheckedRoles(checkedRoles);
		checkedRoleTreeVo.setRoleTree(roleTree);
		return checkedRoleTreeVo;
	}
	/**
	 * 判断一个节点是否全部子孙节点被选中，如果不是，则将该节点从checkedNodeKeys中去掉	
	 * 
	 */	
	private  List<String> redefineCheckedNodeKeys(TreeNode root,Long groupId){
		List<String> checkedNodeKeys = new ArrayList<String>();
		if (groupId!=null && roleGroupDao.exists(groupId)) {
			RoleGroup roleGroup = new RoleGroup();
			roleGroup = (RoleGroup) roleGroupDao.get(groupId);			
			if (roleGroup != null) {
			    List<Role> roles = roleDao.getRolesByRoleGroupId(groupId);
				for (Role role : roles) {
					checkedNodeKeys.add(role.getId().toString());
				}				
			}
			checkedNodeKeys=TreeUtil.redefineCheckedNodeKeys(root, checkedNodeKeys);
		}
		return checkedNodeKeys;
	}
	/**
	 * 从数据库中把全部的Role数据取出，然后创建一颗树
	 * 
	 * @return 返回创建好的树
	 */
	private TreeNode buildTree(Long groupId) {

		Role root = roleDao.getRootRole();
		BasePageSO so = new BasePageSO();
		so.addOrderField("sortIndex");
		so.setOrderType(OrderType.ASC);
		List<Role> poList = roleDao.getAll(so);
		poList.add(root);

		List<FlatTreeNode> flatTreeNodeList = new ArrayList<FlatTreeNode>(
				poList.size() + 1);
		FlatTreeNode flatTreeNode;
		RoleVO nRoleVO;
		for (Role role : poList) {
			nRoleVO = new RoleVO();
			nRoleVO.setId(role.getId());
			
			nRoleVO.setName(role.getName());
			nRoleVO.setParent(role.getParent());
			nRoleVO.setDescription(role.getDescription());
			flatTreeNode = new FlatTreeNode("" + role.getId(), role.getDescription(), "" + role.getParent(), nRoleVO);
			flatTreeNodeList.add(flatTreeNode);
		}

		TreeNode result = TreeUtil.buildTreeFromFlatTreeNodeList(""
				+ root.getId(), flatTreeNodeList, null);
		/*if (roleGroupDao.exists(groupId)) {
			RoleGroup roleGroup = new RoleGroup();
			roleGroup = (RoleGroup) roleGroupDao.get(groupId);
			if (roleGroup != null) {
				List<String> checkedNodeKeys = new ArrayList<String>();
				for (Role role : roleGroup.getRoles()) {
					checkedNodeKeys.add(role.getId().toString());
				}
				checkedNodeKeys = TreeUtil.findAllCheckedNode(result, checkedNodeKeys);
				TreeUtil.markCheckedNode(result, checkedNodeKeys);
			}
		}*/
		return result;
	}
	/**
	 * 获取当前角色组内的权限所构成的树
	 * @param roleGroupVo
	 * @return 成功返回权限树，没有数据返回空的列表
	 */	
	public TreeNode buildSelectedRoleTree(RoleGroupVO roleGroupVo) {
		TreeNode allTreeNode=getTree(roleGroupVo.getId());
		if(allTreeNode==null){
			return allTreeNode;
		}
		List<String> checkedNodeKeys=new ArrayList<String>();
		
        for(RoleVO role:roleGroupVo.getRoles()){
        	checkedNodeKeys.add(role.getId().toString());
          } 
		removeAllUncheckedNodes(allTreeNode, checkedNodeKeys);
		return allTreeNode;
	}
	/**
	 * 删除当前用户没有的权限
	 */
	public  void removeAllUncheckedNodes(TreeNode root, List<String> checkedNodeKeys){
		//标记整棵树中存在的权限
		TreeUtil.markCheckedNode(root, checkedNodeKeys);
		
		class DeleteNodeVisitor implements Visitor{
			public boolean visit(Object o) {
				TreeNode node = (TreeNode)o;
				List<TreeNode> removedChildren = new ArrayList<TreeNode>();
				if(node.getChildren() != null){
					for(TreeNode child : node.getChildren()){
						if(child.getCheckboxState() == 2 && !TreeUtil.isNodeHasDescendantChecked(child)){
							removedChildren.add(child);
						}
					}
					node.getChildren().removeAll(removedChildren);
				}
				return true;
			}
			
		}
		root.traverse(new DeleteNodeVisitor());		
	}
	@SuppressWarnings("unchecked")
	public List<RoleVO> getAll(RoleSO so){
		List<RoleVO> result = new ArrayList<RoleVO>();
        result = (List<RoleVO>)orikaBeanMapper.convertList(roleDao.getAll(so), entityVOClass);
        return result;
	}
	/**
	 * 获取当前登录用户的数据权限角色中父节点的name为parentRoleName的角色列表
	 * @param parentRoleName
	 * @return 成功返回角色列表，没有数据返回空的列表
	 */
	public List<Role> getCurrentUserDataPrivilegeRoles(String parentRoleName){
		List<RoleVO> result = new ArrayList<RoleVO>();
		RoleVO parentRole = getBy("name", parentRoleName);
		if(parentRole == null){
			throw new RuntimeException("Can't find the role:" + parentRole 
					+ ". You should check the Role table to add a role with name '" + parentRole 
					+ "'.");
		}
		
		UserVO currentUser = userService.get(SecurityUtil.getLoginUser().getId());
		List<RoleVO> roles = currentUser.getRoles();
		
		for(RoleVO role : roles){
			if(role.getParent() != null && role.getParent().equals(parentRole.getId())){
				result.add(role);
			}
		}
		return orikaBeanMapper.convertList(result, Role.class);
	}
	
	@Override
	public boolean checkByRole(Long roleId) {
		return roleDao.checkByRole(roleId);
	}
	
	@SuppressWarnings("unchecked")
    @Override
    public List<RoleVO> getRolesByUserID(Long userID) {
        List<RoleVO> result = (List<RoleVO>)orikaBeanMapper.convertList(roleDao.getRolesByUserID(userID), entityVOClass);
        return result;
    }
	
	@SuppressWarnings("unchecked")
    @Override
    public List<RoleVO> getRolesByRoleGroupId(Long id) {
        List<RoleVO> result = (List<RoleVO>)orikaBeanMapper.convertList(roleDao.getRolesByRoleGroupId(id), entityVOClass);
        return result;
    }

}
